/*!
 * \file EventNotifier.cpp
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief 事件通知器实现文件
 * 
 * 实现事件通知器的核心功能：
 * 1. 初始化和管理消息队列连接
 * 2. 将交易事件转换为JSON格式并发布
 * 3. 提供多种类型的事件通知接口
 * 4. 支持实时事件广播和消息推送
 */
#include "EventNotifier.h"
#include "WtHelper.h"

#include "../Share/TimeUtils.hpp"
#include "../Share/DLLHelper.hpp"

#include "../Includes/WTSTradeDef.hpp"
#include "../Includes/WTSCollection.hpp"
#include "../Includes/WTSVariant.hpp"

#include "../WTSTools/WTSLogger.h"

#include <rapidjson/document.h>
#include <rapidjson/prettywriter.h>
namespace rj = rapidjson;

USING_NS_WTP;

/**
 * @brief 消息队列日志回调函数
 * @param id 标识符
 * @param message 日志消息
 * @param bServer 是否为服务器日志
 * 
 * 处理消息队列模块产生的日志信息
 */
void on_mq_log(unsigned long id, const char* message, bool bServer)
{

}

EventNotifier::EventNotifier()
	: _mq_sid(0)
	, _publisher(NULL)
{
	
}

EventNotifier::~EventNotifier()
{
	// 清理消息队列服务器连接
	if (_remover && _mq_sid != 0)
		_remover(_mq_sid);
}

bool EventNotifier::init(WTSVariant* cfg)
{
	// 检查是否启用事件通知功能
	if (!cfg->getBoolean("active"))
		return false;

	// 获取消息队列服务器URL
	m_strURL = cfg->getCString("url");
	std::string module = DLLHelper::wrap_module("WtMsgQue", "lib");
	
	// 先检查当前目录是否有对应模块
	std::string dllpath = WtHelper::getCWD() + module;
	// 如果没有，再检查模块目录，和dll同目录下
	if (!StdFile::exists(dllpath.c_str()))
		dllpath = WtHelper::getInstDir() + module;

	// 加载消息队列模块
	DllHandle dllInst = DLLHelper::load_library(dllpath.c_str());
	if (dllInst == NULL)
	{
		WTSLogger::error("MQ module %s loading failed", dllpath.c_str());
		return false;
	}

	// 获取创建服务器函数
	_creator = (FuncCreateMQServer)DLLHelper::get_symbol(dllInst, "create_server");
	if (_creator == NULL)
	{
		DLLHelper::free_library(dllInst);
		WTSLogger::error("MQ module %s is not compatible", dllpath.c_str());
		return false;
	}

	// 获取其他必要的函数指针
	_remover = (FuncDestroyMQServer)DLLHelper::get_symbol(dllInst, "destroy_server");
	_publisher = (FundPublishMessage)DLLHelper::get_symbol(dllInst, "publish_message");
	_register = (FuncRegCallbacks)DLLHelper::get_symbol(dllInst, "regiter_callbacks");

	// 注册回调函数
	_register(on_mq_log);
	
	// 创建一个MQ服务器
	_mq_sid = _creator(m_strURL.c_str());

	WTSLogger::info("EventNotifier initialized with channel %s", m_strURL.c_str());

	return true;
}

void EventNotifier::notifyLog(const char* tag, const char* message)
{
	std::string data;
	{
		// 构建日志事件的JSON数据
		rj::Document root(rj::kObjectType);
		rj::Document::AllocatorType &allocator = root.GetAllocator();

		root.AddMember("tag", rj::Value(tag, allocator), allocator);
		root.AddMember("time", TimeUtils::getLocalTimeNow(), allocator);
		root.AddMember("message", rj::Value(message, allocator), allocator);

		rj::StringBuffer sb;
		rj::PrettyWriter<rj::StringBuffer> writer(sb);
		root.Accept(writer);

		data = sb.GetString();
	}

	// 发布日志事件
	if (_publisher)
		_publisher(_mq_sid, "LOG", data.c_str(), data.size());
}

void EventNotifier::notifyEvent(const char* message)
{
	std::string data;
	{
		// 构建自定义事件的JSON数据
		rj::Document root(rj::kObjectType);
		rj::Document::AllocatorType &allocator = root.GetAllocator();

		root.AddMember("time", TimeUtils::getLocalTimeNow(), allocator);
		root.AddMember("message", rj::Value(message, allocator), allocator);

		rj::StringBuffer sb;
		rj::PrettyWriter<rj::StringBuffer> writer(sb);
		root.Accept(writer);

		data = sb.GetString();
	}
	
	// 发布自定义事件
	if (_publisher)
		_publisher(_mq_sid, "GRP_EVENT", data.c_str(), data.size());
}

void EventNotifier::notify(const char* trader, const char* message)
{
	std::string data;
	{
		// 构建交易接口消息的JSON数据
		rj::Document root(rj::kObjectType);
		rj::Document::AllocatorType &allocator = root.GetAllocator();

		root.AddMember("trader", rj::Value(trader, allocator), allocator);
		root.AddMember("time", TimeUtils::getLocalTimeNow(), allocator);
		root.AddMember("message", rj::Value(message, allocator), allocator);

		rj::StringBuffer sb;
		rj::PrettyWriter<rj::StringBuffer> writer(sb);
		root.Accept(writer);

		data = sb.GetString();
	}
	
	// 发布交易接口通知
	if (_publisher)
		_publisher(_mq_sid, "TRD_NOTIFY", data.c_str(), data.size());
}

void EventNotifier::notify(const char* trader, uint32_t localid, const char* stdCode, WTSTradeInfo* trdInfo)
{
	if (trdInfo == NULL || _mq_sid == 0)
		return;

	// 将交易信息转换为JSON并发布
	std::string data;
	tradeToJson(trader, localid, stdCode, trdInfo, data);
	if (_publisher)
		_publisher(_mq_sid, "TRD_TRADE", data.c_str(), data.size());
}

void EventNotifier::notify(const char* trader, uint32_t localid, const char* stdCode, WTSOrderInfo* ordInfo)
{
	if (ordInfo == NULL || _mq_sid == 0)
		return;

	// 将订单信息转换为JSON并发布
	std::string data;
	orderToJson(trader, localid, stdCode, ordInfo, data);
	if (_publisher)
		_publisher(_mq_sid, "TRD_ORDER", data.c_str(), data.size());
}

void EventNotifier::tradeToJson(const char* trader, uint32_t localid, const char* stdCode, WTSTradeInfo* trdInfo, std::string& output)
{
	if(trdInfo == NULL)
	{
		output = "{}";
		return;
	}

	// 解析交易信息的关键属性
	bool isLong = (trdInfo->getDirection() == WDT_LONG);
	bool isOpen = (trdInfo->getOffsetType() == WOT_OPEN);
	bool isToday = (trdInfo->getOffsetType() == WOT_CLOSETODAY);

	{
		// 构建交易成交信息的JSON数据
		rj::Document root(rj::kObjectType);
		rj::Document::AllocatorType &allocator = root.GetAllocator();

		root.AddMember("trader", rj::Value(trader, allocator), allocator);
		root.AddMember("time", TimeUtils::getLocalTimeNow(), allocator);
		root.AddMember("localid", localid, allocator);
		root.AddMember("code", rj::Value(stdCode, allocator), allocator);
		root.AddMember("islong", isLong, allocator);
		root.AddMember("isopen", isOpen, allocator);
		root.AddMember("istoday", isToday, allocator);

		root.AddMember("volume", trdInfo->getVolume(), allocator);
		root.AddMember("price", trdInfo->getPrice(), allocator);

		rj::StringBuffer sb;
		rj::PrettyWriter<rj::StringBuffer> writer(sb);
		root.Accept(writer);

		output = sb.GetString();
	}
}

void EventNotifier::orderToJson(const char* trader, uint32_t localid, const char* stdCode, WTSOrderInfo* ordInfo, std::string& output)
{
	if (ordInfo == NULL)
	{
		output = "{}";
		return;
	}

	// 解析订单信息的关键属性
	bool isLong = (ordInfo->getDirection() == WDT_LONG);
	bool isOpen = (ordInfo->getOffsetType() == WOT_OPEN);
	bool isToday = (ordInfo->getOffsetType() == WOT_CLOSETODAY);
	bool isCanceled = (ordInfo->getOrderState() == WOS_Canceled);

	{
		// 构建订单状态信息的JSON数据
		rj::Document root(rj::kObjectType);
		rj::Document::AllocatorType &allocator = root.GetAllocator();

		root.AddMember("trader", rj::Value(trader, allocator), allocator);
		root.AddMember("time", TimeUtils::getLocalTimeNow(), allocator);
		root.AddMember("localid", localid, allocator);
		root.AddMember("code", rj::Value(stdCode, allocator), allocator);
		root.AddMember("islong", isLong, allocator);
		root.AddMember("isopen", isOpen, allocator);
		root.AddMember("istoday", isToday, allocator);
		root.AddMember("canceled", isCanceled, allocator);

		root.AddMember("total", ordInfo->getVolume(), allocator);
		root.AddMember("left", ordInfo->getVolLeft(), allocator);
		root.AddMember("traded", ordInfo->getVolTraded(), allocator);
		root.AddMember("price", ordInfo->getPrice(), allocator);
		root.AddMember("state", rj::Value(ordInfo->getStateMsg(), allocator), allocator);

		rj::StringBuffer sb;
		rj::PrettyWriter<rj::StringBuffer> writer(sb);
		root.Accept(writer);

		output = sb.GetString();
	}
}